﻿using Handy_Domain.DNS.Model;
using Kxx_API.DNS.ALI.DataModel;
using Kxx_API.DNS.ALI.Helper;
using Kxx_Common.Cache;
using Kxx_Common.Net;
using Kxx_Common.Tools;
using Kxx_Domain.DNS;
using Kxx_Domain.DNS.Model;
using Kxx_Log.Log;
using Kxx_Save.DNS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kxx_Services.DNS
{
    public class DNSService
    {
        CDNSHelper dao;

        public DNSService()
        {
            APIConfig config = BascConfig.ALiInfo;
            dao = new CDNSHelper(config?.AccessKeyId, config?.AccessKeySecret, config?.Endpoint);
        }

        /// <summary>
        /// 云解析账号Client刷新
        /// </summary>
        public void CDNSClientRefresh()
        {
            dao.ClientRefresh();
        }

        /// <summary>
        /// 获取域名列表
        /// </summary>
        /// <param name="pageNumber">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <returns></returns>
        public PageBaseModel<DomainModel> GetDNSList(long pageNumber, long pageSize, bool isNew = false)
        {
            string cacheKey = $"DNS_{pageNumber}_{pageSize}";
            PageBaseModel<DomainModel> pageModel = new PageBaseModel<DomainModel>();

            #region 获取缓存
            if (!isNew)
            {
                pageModel = (PageBaseModel<DomainModel>)CacheHelper.GetCache(cacheKey);
                if (pageModel != null)
                {
                    return pageModel;
                }
                else
                {
                    pageModel = new PageBaseModel<DomainModel>();
                }
            }
            #endregion

            #region 获取数据源
            PageBaseDataModel<DomainDataModel> dnsList = dao.GetDNSList(pageNumber, pageSize, isNew);
            #endregion

            #region 日志
            if (dao.IsErr)
            {
                DNSLog.LogAdd(LogType.Error, "获取域名", dao.ErrMsg);
            }
            #endregion

            #region 返回空时处理
            if (dnsList == null) return pageModel;
            #endregion

            #region 页信息
            pageModel.TotalCount = dnsList.TotalCount.ToInt();
            pageModel.PageSize = dnsList.PageSize.ToInt();
            pageModel.PageNumber = dnsList.PageNumber.ToInt();
            #endregion

            #region 转换
            foreach (var item in dnsList.Domains.Domain)
            {
                DomainModel model = new DomainModel();

                CopyHelper.CopyPropertiesTo<DomainDetailsDataModel, DomainModel>(item, model);

                //model.Remark = item.Remark;
                //model.CreateTime = item.CreateTime;
                //model.RecordCount = item.RecordCount;
                //model.InstanceId = item.InstanceId;
                //model.DomainName = item.DomainName;
                //model.DomainId = item.DomainId;
                //model.AliDomain = item.AliDomain;
                //model.GroupId = item.GroupId;
                //model.GroupName = item.GroupName;
                //model.ResourceGroupId = item.ResourceGroupId;
                //model.InstanceEndTime = item.InstanceEndTime;
                //model.InstanceExpired = item.InstanceExpired;
                //model.VersionName = item.VersionName;
                //model.VersionCode = item.VersionCode;
                //model.PunyCode = item.PunyCode;
                //model.RegistrantEmail = item.RegistrantEmail;
                //model.CreateTimestamp = item.CreateTimestamp;
                //model.Starmark = item.Starmark;

                pageModel.list.Add(model);
            }
            #endregion

            #region 缓存（默认300秒）
            CacheHelper.SetCache(cacheKey, pageModel, 300);
            #endregion

            return pageModel;
        }

        /// <summary>
        /// 获取域名解析记录
        /// </summary>
        /// <param name="domainName">域名名称</param>
        /// <param name="pageNumber">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="isNew">是否获取最新</param>
        /// <returns></returns>
        public PageBaseModel<DomainRecordModel> GetDomainRecord(string domainName, long pageNumber, long pageSize, bool isNew = false)
        {
            string cacheKey = $"DomainRecord_{pageNumber}_{pageSize}";
            PageBaseModel<DomainRecordModel> pageModel = new PageBaseModel<DomainRecordModel>();

            #region 获取缓存
            if (!isNew)
            {
                pageModel = (PageBaseModel<DomainRecordModel>)CacheHelper.GetCache(cacheKey);
                if (pageModel != null)
                {
                    return pageModel;
                }
                else
                {
                    pageModel = new PageBaseModel<DomainRecordModel>();
                }
            }
            #endregion

            #region 获取数据源
            PageBaseDataModel<DomainRecordDataModel> domainRecordList = dao.GetDomainRecord(domainName, pageNumber, pageSize, isNew);
            #endregion

            #region 日志
            if (dao.IsErr)
            {
                DNSLog.LogAdd(LogType.Error, "获取域名解析记录", dao.ErrMsg);
            }
            #endregion

            #region 返回空时处理
            if (domainRecordList == null) return pageModel;
            #endregion

            #region 页信息
            pageModel.TotalCount = domainRecordList.TotalCount.ToInt();
            pageModel.PageSize = domainRecordList.PageSize.ToInt();
            pageModel.PageNumber = domainRecordList.PageNumber.ToInt();
            #endregion

            #region 转换
            foreach (var item in domainRecordList.DomainRecords.Record)
            {
                DomainRecordModel model = new DomainRecordModel();

                CopyHelper.CopyPropertiesTo<DomainRecordDetailsDataModel, DomainRecordModel>(item, model);

                pageModel.list.Add(model);
            }
            #endregion

            #region 缓存（默认300秒）
            CacheHelper.SetCache(cacheKey, pageModel, 300);
            #endregion

            return pageModel;
        }

        /// <summary>
        /// 获取解析记录是否存在
        /// </summary>
        /// <param name="recordId"></param>
        /// <returns></returns>
        public bool GetRecordIsExists(string recordId)
        {
            var model = dao.GetDomainRecordDetails(recordId);
            if (model == null) return false;

            return true;
        }

        /// <summary>
        /// 更新解析记录
        /// </summary>
        /// <param name="recordId">解析记录的ID</param>
        /// <param name="rr">主机记录</param>
        /// <param name="type">解析记录类型</param>
        /// <param name="value">记录值</param>
        /// <returns></returns>
        public void UpdateDomainRecord(string recordId, string rr, string type, string value)
        {
            new Task(() => {
                try
                {
                    #region 空值验证
                    if (recordId.IsEmpty())
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID为空");
                        return;
                    }

                    if (rr.IsEmpty())
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】的主机记录为空");
                        return;
                    }

                    if (type.IsEmpty())
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】的记录类型为空");
                        return;
                    }

                    if (value.IsEmpty())
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】的记录值为空");
                        return;
                    }
                    #endregion

                    #region 获取解析记录详细信息，验证是否需要更新
                    string cacheKey = $"DomainRecordDetails_{recordId}";
                    DomainRecordDetailsDataModel model = dao.GetDomainRecordDetails(recordId);

                    if (dao.IsErr)
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】获取最新记录遇到错误：{dao.ErrMsg}");
                        return;
                    }

                    if (model == null)
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】获取最新记录为空");
                        return;
                    }

                    if (model.RR == rr && model.Type == type && model.Value == value)
                    {
                        DNSLog.LogAdd(LogType.Info, "更新域名解析记录", $"解析记录ID【{recordId}】无更新");
                        return;
                    }
                    #endregion

                    bool bl = dao.UpdateDomainRecord(recordId, rr, type, value);
                    bool emailBl = NoticeQQEmail(recordId, value);

                    if (dao.IsErr)
                    {
                        DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】更新解析记录遇到错误：{dao.ErrMsg}");
                        return;
                    }

                    if (!emailBl)
                    {
                        DNSLog.LogAdd(LogType.Error, "通知QQEmail", $"解析记录ID【{recordId}】值【{value}】通知失败!");
                    }

                    DNSLog.LogAdd(LogType.Info, "更新域名解析记录", $"解析记录ID【{recordId}】更新一次");
                }
                catch(Exception ex)
                {
                    DNSLog.LogAdd(LogType.Error, "更新域名解析记录", $"解析记录ID【{recordId}】遇到错误：{ex.Message}");
                }
            }).Start();
        }

        /// <summary>
        /// 通知QQ Email
        /// </summary>
        /// <param name="recordId"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool NoticeQQEmail(string recordId, string value)
        {
            string subject = "解析记录发生变化";
            StringBuilder strWhere = new StringBuilder();
            strWhere.Append($"<div style=\"width: 40%; min-width: 500px; margin: 0 auto;\">");
            strWhere.Append($"  <h2>主机【{NetHelper.LocalHostName}】解析记录通知：</h2>");
            strWhere.Append($"  <div style=\"text-indent:50px;\">");
            strWhere.Append($"    <p>解析记录号：{recordId}</p>");
            strWhere.Append($"    <p>解析记录值：{value}</p>");
            strWhere.Append($"  </div>");
            strWhere.Append($"</div>");

            try
            {
                EmailHelper.SendQQEmail(BascConfig.QQEmailInfo.FromAddr, BascConfig.QQEmailInfo.Psw, BascConfig.QQEmailInfo.ToAddr, subject, strWhere.ToString());
                return true;
            }
            catch(Exception ex) { return false; }
        }
    }
}
